﻿using GACore.Structures;
using System;

namespace GACore.Helpers
{
	public class ReplacementHelper
	{
		ReplacementProperties replacementProperties;

		public ReplacementHelper(ReplacementProperties replacementProperties)
		{
			this.replacementProperties = replacementProperties;
		}

		public Vector[] Replace(Vector[] parents, Vector[] children)
		{
			switch (replacementProperties.Schema)
			{
				case ReplacementSchema.NotElitistic:
					return ReplaceNotElitistic(parents, children);
				case ReplacementSchema.StandardElitistic:
					return ReplaceStandardElitistic(parents, children);
				case ReplacementSchema.Elitistic:
					return ReplaceElitistic(parents, children);
				case ReplacementSchema.DeleteNLast:
					return ReplaceDeleteNLast(parents, children);
				default:
					throw new ArgumentException(replacementProperties.Schema + " ist kein mögliches Crossover-Schema.");
			}
		}

		private Vector[] ReplaceNotElitistic(Vector[] parents, Vector[] children)
		{
			if (children.Length == parents.Length)
			{
				return children;
			}
			else
			{
				Vector[] ret = new Vector[parents.Length];
				Array.Copy(children, ret, ret.Length);
				return ret;
			}
		}
		private Vector[] ReplaceElitistic(Vector[] parents, Vector[] children)
		{
			Vector[] ret = new Vector[parents.Length];
			Vector[] tmp = new Vector[parents.Length + children.Length];
			Array.Copy(parents, tmp, parents.Length);
			Array.Copy(children, 0, tmp, parents.Length, children.Length);
			Array.Sort(tmp);
			Array.Copy(tmp, ret, ret.Length);
			return ret;
		}

		private Vector[] ReplaceDeleteNLast(Vector[] parents, Vector[] children)
		{
			Vector[] ret = new Vector[parents.Length];
			Array.Copy(parents, ret, parents.Length - replacementProperties.ReplacementCount);
			Array.Copy(children, 0, ret, ret.Length - replacementProperties.ReplacementCount, replacementProperties.ReplacementCount);
			Array.Sort(ret);
			return ret;
		}

		private Vector[] ReplaceStandardElitistic(Vector[] parents, Vector[] children)
		{
			Vector[] ret = new Vector[parents.Length];
			Array.Copy(children, ret, ret.Length);
			if (parents[parents.Length - 1].CompareTo(children[0]) < 0)
			{
				Array.Copy(parents, 0, ret, ret.Length - replacementProperties.ReplacementCount, replacementProperties.ReplacementCount);
			}
			return ret;
		}

	}
}
